package com.campus.customer.service;

import cn.hutool.core.date.DateTime;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.campus.common.bean.common.Resp;
import com.campus.common.constants.GlobalConstant;
import com.campus.customer.entity.DeliveryUser;
import com.campus.customer.entity.User;
import com.campus.customer.mapper.DeliveryUserMapper;
import com.campus.customer.mapper.UserMapper;
import com.campus.customer.vo.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

@Service
@Slf4j
public class WechatAuthService {
    private static final String GET_ACCESS_TOKEN_URL =
            "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

    private static final String GET_PHONE_NUMBER_URL = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=%s";

    // accessToken有效期（秒）
    private static final long ACCESS_TOKEN_EXPIRE = 1800; // 30分钟
    // refreshToken有效期（秒）
    private static final long REFRESH_TOKEN_EXPIRE = 7 * 86400L; // 7天
    
    @Value("${wechat.appid}")
    private String appid;
    
    @Value("${wechat.secret}")
    private String secret;
    
    @Value("${campus.wechat.transaction-fee-rate}")
    private double wechatTransactionFeeRate;
    
    @Value("${campus.wechat.max-split-rate}")
    private double wechatMaxSplitRate;
    
    @Value("${campus.profit.service-fee-rate}")
    private double serviceFeeRate;
    
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RedisService redisService;
    
    @Autowired
    private CouponService couponService;
    
    @Autowired
    private DeliveryUserMapper deliveryUserMapper;
    
    /**
     * 微信小程序静默登录，返回accessToken和refreshToken
     * @param code 微信登录code
     * @return Resp 包含accessToken、refreshToken和用户信息
     */
    public Resp wxLogin(String code) {
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                appid, secret, code);
        String responseBody = HttpUtil.get(url);
        JSONObject response = JSONUtil.parseObj(responseBody);
        if (response == null || response.containsKey("errcode")) {
            return Resp.error("微信登录失败: " + (response != null ? response.getStr("errmsg") : "未知错误"));
        }
        String openid = response.getStr("openid");
        String sessionKey = response.getStr("session_key");
        // 查询或创建用户
        User user = userMapper.selectByOpenid(openid);
        boolean isNewUser = false;
        if (user == null) {
            user = new User();
            user.setOpenid(openid);
            userMapper.insert(user);
            isNewUser = true;
            
            // 为新用户自动发放优惠券
            try {
                couponService.grantNewUserCoupons(user.getId());
            } catch (Exception e) {
                log.error("新用户优惠券发放失败，用户ID: {}, 错误: {}", user.getId(), e.getMessage());
            }
        }
        // 生成accessToken和refreshToken
        String accessToken = generateToken(user, "access");
        String refreshToken = generateToken(user, "refresh");
        // 存入redis
        UserInfoVo userInfoVo = new UserInfoVo();
        BeanUtils.copyProperties(user, userInfoVo);
        userInfoVo.setToken(accessToken);
        redisService.set(accessToken, JSON.toJSONString(userInfoVo), ACCESS_TOKEN_EXPIRE);
        redisService.set(refreshToken, JSON.toJSONString(userInfoVo), REFRESH_TOKEN_EXPIRE);
        
        // 根据微信分账规则计算配送费与实付金额的比率
        // 微信分账限制：订单实付金额×(1-微信手续费)×最大分账比例 - 订单实付金额×运营平台抽佣比例 ≥ 配送费
        // 即：实付金额×((1-微信手续费)×最大分账比例 - 运营平台抽佣比例) ≥ 配送费
        // 所以：配送费/实付金额 ≤ (1-微信手续费)×最大分账比例 - 运营平台抽佣比例
        double availableSplitRate = (1 - wechatTransactionFeeRate) * wechatMaxSplitRate - serviceFeeRate;
        double deliveryFeeRatio = Math.max(0, availableSplitRate);
        
        // 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("accessToken", accessToken);
        result.put("refreshToken", refreshToken);
        result.put("userInfo", userInfoVo);
        result.put("isNewUser", isNewUser);
        result.put("deliveryFeeRatio", deliveryFeeRatio);
        return Resp.success(result);
    }

    /**
     * 刷新token
     * @param refreshToken refreshToken
     * @return Resp 新accessToken和refreshToken
     */
    public Resp refreshToken(String refreshToken) {
        // 校验refreshToken
        String userInfoStr = redisService.get(refreshToken);
        if (userInfoStr == null) {
            return Resp.error("refreshToken无效或已过期");
        }
        UserInfoVo userInfoVo = JSON.parseObject(userInfoStr, UserInfoVo.class);
        // 生成新accessToken和refreshToken
        User user = new User();
        BeanUtils.copyProperties(userInfoVo, user);
        String newAccessToken = generateToken(user, "access");
        String newRefreshToken = generateToken(user, "refresh");
        // 存入redis
        userInfoVo.setToken(newAccessToken);
        redisService.set(newAccessToken, JSON.toJSONString(userInfoVo), ACCESS_TOKEN_EXPIRE);
        redisService.set(newRefreshToken, JSON.toJSONString(userInfoVo), REFRESH_TOKEN_EXPIRE);
        // 删除旧refreshToken
        redisService.remove(refreshToken);
        // 返回新token
        Map<String, Object> result = new HashMap<>();
        result.put("accessToken", newAccessToken);
        result.put("refreshToken", newRefreshToken);
        return Resp.success(result);
    }

    /**
     * 生成token
     */
    private String generateToken(User user, String type) {
        return MD5.create().digestHex((user.getOpenid() != null ? user.getOpenid() : "customer") + type + java.util.UUID.randomUUID().toString() + DateTime.now().toString("yyyyMMddHHmmss"));
    }

    /**
     * 获取小程序全局唯一后台接口调用凭据AccessToken
     * @return
     */
    public String getAccessToken() {
        String accessTokenInRedis = redisService.get(GlobalConstant.WECHAT_ACCESS_TOKEN + appid);

        if(StringUtils.isNotBlank(accessTokenInRedis)){
            return accessTokenInRedis;
        }

        String url = String.format(GET_ACCESS_TOKEN_URL, appid, secret);
        String result = HttpUtil.get(url, StandardCharsets.UTF_8);

        log.info("获取accessToken接口返回结果：{}", result);

        JSONObject resultJO = JSONUtil.parseObj(result);

        String accessToken = resultJO.getStr("access_token");
        Long expiresIn = resultJO.getLong("expires_in");

        //TODO 保存到redis
        if(StringUtils.isNotBlank(accessToken)){
            redisService.set(GlobalConstant.WECHAT_ACCESS_TOKEN + appid, accessToken, expiresIn-100);
        }

        return accessToken;
    }


    public String getWechatPhoneNumber(String code) {
        String url = String.format(GET_PHONE_NUMBER_URL, getAccessToken());
        Map<String, Object> map = new HashMap<>();
        map.put("code", code);
        String result = HttpUtil.post(url, JSONUtil.toJsonStr(map));
        log.info("获取手机号接口返回结果：{}", result);
        if (result != null) {
            JSONObject resultJO = JSONUtil.parseObj(result);
            int errcode = resultJO.getInt("errcode");
            if (errcode != 0) {
                String errmsg = resultJO.getStr("errmsg");
                log.error("获取手机号失败：{}", errmsg);
                return null;
            }
            JSONObject phoneInfo = resultJO.getJSONObject("phone_info");
            String phoneNumber = phoneInfo.getStr("phoneNumber");

            return phoneNumber;
        }
        return null;
    }

    /**
     * 保存配送员在顾客端的openid
     * @param code 微信登录code
     * @param deliveryOpenid 配送员在配送端的openid
     * @return 操作结果
     */
    public Resp saveDeliveryCustomerOpenid(String code, String deliveryOpenid) {
        // 1. 通过code获取顾客端openid
        String url = String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
                appid, secret, code);
        String responseBody = HttpUtil.get(url);
        JSONObject response = JSONUtil.parseObj(responseBody);
        
        if (response == null || response.containsKey("errcode")) {
            return Resp.error("获取顾客端openid失败: " + (response != null ? response.getStr("errmsg") : "未知错误"));
        }
        
        String customerOpenid = response.getStr("openid");
        
        // 2. 根据配送员openid查询配送员记录
        DeliveryUser deliveryUser = deliveryUserMapper.selectOne(
            new com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<DeliveryUser>()
                .eq("openid", deliveryOpenid)
        );
        
        if (deliveryUser == null) {
            return Resp.error("配送员不存在");
        }
        
        // 3. 更新配送员的顾客端openid
        deliveryUser.setCustomerOpenid(customerOpenid);
        int updateResult = deliveryUserMapper.updateById(deliveryUser);
        
        if (updateResult > 0) {
            log.info("配送员{}的顾客端openid更新成功: {}", deliveryOpenid, customerOpenid);
            return Resp.success("openid绑定成功");
        } else {
            return Resp.error("openid绑定失败");
        }
    }

}